/*
 * Copyright [2022] [https://www.xiaonuo.vip]
 *
 * Snowy采用APACHE LICENSE 2.0开源协议，您在使用过程中，需要注意以下几点：
 *
 * 1.请不要删除和修改根目录下的LICENSE文件。
 * 2.请不要删除和修改Snowy源码头部的版权声明。
 * 3.本项目代码可免费商业使用，商业使用请保留源码和相关描述文件的项目出处，作者声明等。
 * 4.分发源码时候，请注明软件出处 https://www.xiaonuo.vip
 * 5.不可二次分发开源参与同类竞品，如有想法可联系团队xiaonuobase@qq.com商议合作。
 * 6.若您的项目无法满足以上几点，需要更多功能代码，获取Snowy商业授权许可，请在官网购买授权，地址为 https://www.xiaonuo.vip
 */
package com.shengqin.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.shengqin.common.pojo.CommonPage;
import com.shengqin.config.CommonException;
import com.shengqin.entity.Standard;
import com.shengqin.entity.SysHealthProject;
import com.shengqin.mapper.StandardMapper;
import com.shengqin.pojo.plan.result.ScoreResult;
import com.shengqin.pojo.plan.result.TestResultKey;
import com.shengqin.service.IStandardService;
import com.shengqin.utils.GradeUtil;
import com.shengqin.utils.ProjectUtil;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 评分标准Service接口实现类
 *
 * @author Rui.Zhou
 * @date 2022/12/23 16:53
 **/
@Service
public class StandardServiceImpl extends ServiceImpl<StandardMapper, Standard> implements IStandardService {

    @Override
    public List<Standard> listByPrjAndSexAndGrade(TestResultKey resultKey, Integer templateId) {
        QueryWrapper<Standard> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("sex", resultKey.getSex());
        queryWrapper.eq("grade_id", resultKey.getGradeId());
        queryWrapper.eq("project_name", resultKey.getPrjName());
        queryWrapper.lambda().eq(Standard::getTemplateId, templateId);
        queryWrapper.orderByDesc("score");
        return list(queryWrapper);
    }

    public BigDecimal transferResult(String result, String radixType, Integer radixLength) {
        if (StringUtils.hasLength(result)) {
            if (result.contains(":")) {
                result = result.replaceAll("\\.", ":");
                String[] texts = result.split(":");
                BigDecimal minutes = new BigDecimal(Integer.parseInt(texts[0]) * 60);
                BigDecimal second = new BigDecimal(Integer.parseInt(texts[1]));
                BigDecimal millisecond = new BigDecimal(Integer.parseInt(texts[2])).divide(new BigDecimal("1000"), 3, RoundingMode.DOWN);
                if (StringUtils.hasLength(radixType)) {
                    BigDecimal millisecondDecimal = transferMillisecond(texts[2], radixType, radixLength);
                    return minutes.add(second).add(millisecondDecimal);
                }
                return minutes.add(second).add(millisecond);
            } else if ((result.contains("'") || result.contains("′"))) {
                String finalValue = result;
                finalValue = finalValue.replaceAll("'", "′");
                finalValue = finalValue.replaceAll("\"", "″");

                String[] values = finalValue.split("′");
                Integer valueMin = Integer.parseInt(values[0]) * 60;
                Integer valueSecond = Integer.valueOf(values[1].replaceAll("″", ""));
                return new BigDecimal(valueMin + valueSecond);
            } else {
                return new BigDecimal(result);
            }
        }
        return null;
    }

    private BigDecimal transferMillisecond(String millisecondText, String radixType, Integer radixLength) {
        BigDecimal millisecondDecimal = new BigDecimal(millisecondText);
        if (radixType.equalsIgnoreCase("不取舍")) {
            if (radixLength == 0) {
                return BigDecimal.ZERO;
            }
            if (millisecondText.length() >= 2) {
                String millisecondText2 = millisecondText.substring(0, 1);
                return new BigDecimal(millisecondText2 + "00").divide(new BigDecimal("1000"), radixLength, RoundingMode.HALF_UP);
            }
        } else {
            BigDecimal divide = millisecondDecimal.divide(new BigDecimal("1000"), radixLength, RoundingMode.HALF_UP);
            if (radixType.equalsIgnoreCase("非零进一")) {
                if (millisecondText.length() >= 2) {
                    String millisecondText2 = millisecondText.substring(1, 2);
                    if (millisecondText2.equals("0")) {
                        return divide;
                    } else {
                        return millisecondDecimal.divide(new BigDecimal("1000"), radixLength, RoundingMode.UP);
                    }
                }
            } else if (radixType.equalsIgnoreCase("四舍五入")) {
                return divide;
            }
        }
        return millisecondDecimal.divide(new BigDecimal("1000"), 3, RoundingMode.DOWN);
    }

    @Override
    public ScoreResult buildScoreResult(String result, List<Standard> standardList, SysHealthProject project, Integer calculateType, Integer radixLength) {
        ScoreResult scoreResult = new ScoreResult();
        String radixType = project.getRadixType();
        BigDecimal realResult = transferResult(result, calculateType == 2 ? radixType : "", radixLength);
        if (realResult == null) {
            return null;
        }
        String prjName = standardList.get(0).getProjectName();
        String projectType = project.getPrjType();
        scoreResult.setRealResult(realResult);
        if ("BMI".equalsIgnoreCase(prjName)) {
            List<Standard> bmiStandardList = standardList.stream().sorted(Comparator.comparing(Standard::getTestValue).reversed()).collect(Collectors.toList());
            for (int i = 0; i < bmiStandardList.size(); i++) {
                Standard standard = bmiStandardList.get(i);
                BigDecimal standardResult = new BigDecimal(standard.getTestValue());
                if (realResult.compareTo(standardResult) >= 0) {
                    scoreResult.setScore(standard.getScore());
                    scoreResult.setLevel(standard.getLevel());
                    if (standard.getScore().compareTo(new BigDecimal("100")) > 0) {
                        scoreResult.setStandardScore(new BigDecimal("100"));
                        scoreResult.setExtraScore(standard.getScore().subtract(new BigDecimal("100")));
                    } else {
                        scoreResult.setStandardScore(standard.getScore());
                        scoreResult.setExtraScore(BigDecimal.ZERO);
                    }
                    scoreResult.setStandardResult(standardResult);
                    break;
                } else {
                    if (i == bmiStandardList.size() - 1) {
                        scoreResult.setStandardResult(standardResult);
                        scoreResult.setScore(standard.getScore());
                        scoreResult.setLevel(standard.getLevel());
                        scoreResult.setStandardScore(standard.getScore());
                        scoreResult.setExtraScore(BigDecimal.ZERO);
                    }
                }
            }
        } else {
            for (Standard standard : standardList) {
                BigDecimal standardResult;
                if (standard.getTestValue().contains("'") || standard.getTestValue().contains("′")) {
                    String finalValue = standard.getTestValue();
                    finalValue = finalValue.replaceAll("'", "′");
                    finalValue = finalValue.replaceAll("\"", "″");

                    String[] values = finalValue.split("′");
                    Integer valueMin = Integer.parseInt(values[0]) * 60;
                    Integer valueSecond = Integer.valueOf(values[1].replaceAll("″", ""));
                    standardResult = new BigDecimal(valueMin + valueSecond);
                } else {
                    standardResult = new BigDecimal(standard.getTestValue());
                }
                boolean goOn;
                if (StringUtils.hasLength(projectType) && (projectType.contains("计时") || projectType.equalsIgnoreCase("计时"))) {
                    goOn = realResult.compareTo(standardResult) <= 0;
                } else {
                    goOn = realResult.compareTo(standardResult) >= 0;
                }
                if (goOn) {
                    scoreResult.setStandardResult(standardResult);
                    scoreResult.setScore(standard.getScore());
                    scoreResult.setLevel(standard.getLevel());
                    if (standard.getScore().compareTo(new BigDecimal("100")) > 0) {
                        scoreResult.setStandardScore(new BigDecimal("100"));
                        scoreResult.setExtraScore(standard.getScore().subtract(new BigDecimal("100")));
                    } else {
                        scoreResult.setStandardScore(standard.getScore());
                        scoreResult.setExtraScore(BigDecimal.ZERO);
                    }
                    break;
                }
            }
        }

        if (result.equalsIgnoreCase("-1006") || result.equalsIgnoreCase("-1002")) {
            scoreResult.setStandardScore(BigDecimal.ZERO);
            scoreResult.setExtraScore(BigDecimal.ZERO);
            scoreResult.setScore(BigDecimal.ZERO);
            scoreResult.setLevel("不及格");
        }
        return scoreResult;
    }

    @Override
    public Page<Standard> getPage(CommonPage<Standard> pageParam) {
        QueryWrapper<Standard> queryWrapper = new QueryWrapper<>();
        Standard queryParam = pageParam.getQueryParam();
        if (ObjectUtil.isNotEmpty(queryParam.getGradeId())) {
            queryWrapper.lambda().eq(Standard::getGradeId, queryParam.getGradeId());
        }
        if (ObjectUtil.isNotEmpty(queryParam.getSex())) {
            queryWrapper.lambda().eq(Standard::getSex, queryParam.getSex());
        }
        if (ObjectUtil.isNotEmpty(queryParam.getPrjCode())) {
            queryWrapper.lambda().eq(Standard::getPrjCode, queryParam.getPrjCode());
        }
        if (ObjectUtil.isNotEmpty(queryParam.getProjectName())) {
            queryWrapper.lambda().like(Standard::getProjectName, queryParam.getProjectName());
        }
        queryWrapper.lambda().eq(Standard::getTemplateId, queryParam.getTemplateId());
        Page<Standard> standardPage = new Page<>(pageParam.getPageNo(), pageParam.getPageSize());
        page(standardPage, queryWrapper);
        buildRecords(standardPage.getRecords());
        return standardPage;
    }

    @Override
    public List<Standard> listByTemplateId(Integer templateId) {
        QueryWrapper<Standard> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(Standard::getTemplateId, templateId);
        return list(queryWrapper);
    }

    @Override
    public void importBatch(List<Standard> cachedDataList, Integer templateId) {
        try {
            cachedDataList.forEach(standard -> {
                standard.setTemplateId(templateId);
            });

            saveOrUpdateBatch(cachedDataList);
        } catch (Exception e) {
            log.error("导入评分标准报错", e);
            throw new CommonException("导入评分标准报错" + e.getMessage());
        }
    }

    @Override
    public void removeByTemplateId(Integer templateId) {
        QueryWrapper<Standard> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(Standard::getTemplateId, templateId);
        remove(wrapper);
    }

    @Override
    public List<Standard> listStandardPrjByTemplateId(Integer templateId, String sex, Integer gradeId) {
        QueryWrapper<Standard> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(Standard::getTemplateId, templateId);
        wrapper.lambda().eq(Standard::getSex,sex);
        wrapper.lambda().eq(Standard::getGradeId,gradeId);
        List<Standard> standards = list(wrapper);
        return standards;
    }

    private void buildRecords(List<Standard> records) {
        if (!CollectionUtils.isEmpty(records)) {
            records.forEach(record -> {
                record.setGradeName(GradeUtil.getGradeName(Integer.valueOf(record.getGradeId())));
                String name = ProjectUtil.getPrjName(record.getPrjCode());
                record.setProjectName(StringUtils.hasLength(name) ? name : record.getProjectName());
            });
        }
    }
}
